// Prim算法优化（洛谷）
// 静态空间实现
// 时间复杂度O(n + m) + O((m+n) * log n)
// 测试链接 : https://www.luogu.com.cn/problem/P3366
// 提交以下所有代码，可以直接通过

#include <iostream>
#include <algorithm>

using namespace std;

// 建图用链式前向星
// 堆也是用数组结构手写的、且只和节点个数有关
// 这个实现留给有需要的同学
// 但是一般情况下并不需要做到这个程度

const int MAXN = 5001;
const int MAXM = 400001;

// 链式前向星建图
int head[MAXN];
int next[MAXM];
int to[MAXM];
int weight[MAXM];
int cnt;

// 改写的堆结构
int heap[MAXN][2];

// where[v] = -1，表示 v 这个节点，从来没有进入过堆
// where[v] = -2，表示 v 这个节点，已经弹出过了
// where[v] = i(>=0)，表示 v 这个节点，在堆上的 i 位置
int where[MAXN];

// 堆的大小
int heapSize;

// 找到的节点个数
int nodeCnt;

// u 和 w 用来接收堆弹出的数据
int u, w;

// 题目输入的参数
int n, m;

void build()
{
    cnt = 1;
    heapSize = 0;
    fill(head + 1, head + n + 1, 0);
    fill(where + 1, where + n + 1, -1);
}

void addEdge(int u, int v, int w)
{
    ::next[cnt] = head[u];
    to[cnt] = v;
    weight[cnt] = w;
    head[u] = cnt++;
}

// 堆上，i 位置的信息 和 j 位置的信息 交换！
void swap(int i, int j)
{
    int u = heap[i][0], v = heap[j][0];
    where[u] = j, where[v] = i;
    std::swap(heap[i], heap[j]); 
}

// 向上调整算法
void heapInsert(int i)
{
    while(heap[i][1] < heap[(i - 1) / 2][1])
    {
        ::swap(i, (i - 1) / 2);
        i = (i - 1) / 2;
    }
}

// 当前处理的是编号为 ei 的边！
void addOrUpdateOrIgnore(int ei)
{
    int v = to[ei], w = weight[ei];
    // 去往节点 v，权重为 w
    if(where[v] == -1)
    {
        // v 这个点，从来没有进入过堆！
        heap[heapSize][0] = v;
        heap[heapSize][1] = w;
        where[v] = heapSize++;
        heapInsert(where[v]);
    }
    else if(where[v] >= 0)
    {
        // v 这个点的记录，在堆上的位置是 where[v] 
        heap[where[v]][1] = min(heap[where[v]][1], w);
        heapInsert(where[v]);
    }
}

bool isEmpty()
{
    return heapSize == 0;
}

void heapify(int i)
{
    int l = 2 * i + 1;
    while(l < heapSize)
    {
        int best = l + 1 < heapSize && heap[l + 1][1] < heap[l][1] ? l + 1 : l;
        best = heap[best][1] < heap[i][1] ? best : i;
        if(best == i) break;
        swap(best, i);
        i = best;
        l = 2 * i + 1;
    }
}

// 堆顶的记录：节点 -> u、到节点的花费 -> w
void pop()
{
    u = heap[0][0];
    w = heap[0][1];
    ::swap(0, --heapSize);
    heapify(0);
    where[u] = -2;
    ++nodeCnt;
}

int prim()
{
    nodeCnt = 1;
    where[1] = -2;
    for(int ei = head[1]; ei > 0; ei = ::next[ei])
    {
        addOrUpdateOrIgnore(ei);
    }

    int ans = 0;
    while(!isEmpty())
    {
        pop();
        ans += w;
        for(int ei = head[u]; ei > 0; ei = ::next[ei])
        {
            addOrUpdateOrIgnore(ei);
        }
    }
    return ans;
}

int main()
{
    cin >> n >> m;
    build();
    for(int i = 0; i < m; ++i)
    {
        int u, v, w;
        cin >> u >> v >> w;
        addEdge(u, v, w);
        addEdge(v, u, w);
    }

    int ans = prim();
    if(nodeCnt == n)
        cout << ans << endl;
    else
        cout << "orz" << endl;

    return 0;
}